<?php
/**
 * Slipstream :: Highly adaptive dependency injection framework
 * Copyright 2010-2011 Ian Unruh (Xerof3ar)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
namespace Slipstream\Infrastructure\Context\Type;

use SplObjectStorage;
use Slipstream\Configuration\ContextInterface;

/**
 * Base implementation of ResolverServiceInterface
 * 
 * @author Ian Unruh (Xerof3ar) <ianunruh@gmail.com>
 * @since Class avaliable since release 1.0
 */
class ResolverService implements ResolverServiceInterface
{
	/**
	 * @var SplObjectStorage<ResolverInterface>
	 */
	protected $resolvers;
	
	/**
	 * Class constructor
	 * @return void
	 */
	public function __construct()
	{
		$this->resolvers = new SplObjectStorage();
	}
	
	/**
	 * Attempts to resolve a context to a class or interface type
	 * 
	 * @param ContextInterface $context
	 * @return string|false Returns false if identifier could not be resolved
	 */
	public function resolveType(ContextInterface $context)
	{
		$resolution = new ResolutionContext($context);
		
		foreach($this->resolvers as $resolver) {
			$resolver->resolve($resolution);
			
			switch($resolution->getResult()) {
				case ResolutionResult::Resolved:
					return $resolution->getResolvedType();
				case ResolutionResult::Alias:
					$resolution->setResult(ResolutionResult::NotResolved());
					$this->resolvers->rewind();
					continue;
			}
		}
		return false;
	}
	
	/**
	 * Registers a resolver with this service
	 * 
	 * @param ResolverInterface $resolver
	 * @return void
	 */
	public function register(ResolverInterface $resolver)
	{
		$this->resolvers->attach($resolver);
	}
	
	/**
	 * Unregisters a resolver from this service
	 * 
	 * @param ResolverInterface $resolver
	 * @return void
	 */
	public function unregister(ResolverInterface $resolver)
	{
		$this->resolvers->detach($resolver);
	}
	
	/**
	 * Returns the resolvers registered to this resolver service
	 * @return SplObjectStorage<ResolverInterface>
	 */
	public function getResolvers()
	{
		return $this->resolvers;
	}
}